package org.nerve.okhttp3.cookie;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import okhttp3.Cookie;
import okhttp3.HttpUrl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 将cookie保存到JSON中
 * org.nerve.okhttp3
 * Created by zengxm on 2016/7/25.
 */
public class JsonCookieStore implements ICookieStore {
	/**
	 * 默认的保存了Cookie的文件名
	 */
	public final static String COOKIES="cookies.json";

	protected String cookieFile;    //保存Cookie信息的json文件
	protected final Map<String, Map<String,Cookie>> cookies = new HashMap<>();

	public JsonCookieStore(){}

	public JsonCookieStore(String filePath){
		this.cookieFile=filePath;
	}

	protected InputStream getCookieFileInputStream() throws IOException {
		if(cookieFile==null || cookieFile.trim().length()==0)
			return JsonCookieStore.class.getResourceAsStream("/"+COOKIES);
		else{
			File file=new File(cookieFile);
			//文件不存在，则创建新文件，并写入数据
			if(!file.exists()){
				Files.write(Paths.get(file.toURI()), "[]".getBytes(), StandardOpenOption.CREATE_NEW);
				System.out.println("create cookies file : "+file.getAbsolutePath());
			}
			return new FileInputStream(cookieFile);
		}
	}

	/**
	 * 在指定的文件中加载cookie
	 */
	public void loadCookie() throws IOException {
		InputStream is= getCookieFileInputStream();

		try{
			JSONArray array=JSON.parseObject(is, JSONArray.class);
			array.forEach(item->{
				HostCookie hostCookie = JSON.parseObject(item.toString(), HostCookie.class);
				if(!cookies.containsKey(hostCookie.getHost())){
					cookies.put(hostCookie.getHost(), new ConcurrentHashMap<>());
				}
				//cookie放到cookies中
				hostCookie.getOkHttpCookies().forEach(cookie -> cookies.get(hostCookie.getHost()).put(getCookieToken(cookie), cookie));
			});
		}catch (JSONException jsonException){
			System.out.println("JSON parse error, empty cookies!");
		}

		if(is!=null){
			is.close();
		}
	}

	/**
	 *
	 * @param cookie
	 * @return
	 */
	protected String getCookieToken(Cookie cookie) {
		return cookie.name();
	}

	public void add(HttpUrl url, Cookie cookie){
		System.out.println("增加cookie:"+url+"(host="+url.host()+") >>> "+cookie);
		String host=url.host();
		if(!cookies.containsKey(host))
			cookies.put(host, new ConcurrentHashMap<>());

		cookies.get(host).put(getCookieToken(cookie), cookie);
	}

	public List<Cookie> get(HttpUrl url){
		ArrayList<Cookie> ret = new ArrayList<>();
		if (cookies.containsKey(url.host()))
			ret.addAll(cookies.get(url.host()).values());
		return ret;
	}

	@Override
	public Cookie get(String host, String name) {
		if(cookies.containsKey(host)){
			return cookies.get(host).get(name);
		}
		return null;
	}

	@Override
	public void persistent() {
		//转换成List<HostCookie>
		List<HostCookie> hostCookies=new CopyOnWriteArrayList<>();
		cookies.forEach((k, v) -> {
			HostCookie hostCookie=new HostCookie(k);
			v.values().forEach(c->hostCookie.add(c));

			hostCookies.add(hostCookie);
		});

		//保存到文件
		try{
			Path path=(cookieFile==null || cookieFile.trim().length()==0)?
					Paths.get(getClass().getResource("/"+COOKIES).toURI())
					:
					Paths.get(cookieFile);
			Files.write(path, JSON.toJSONString(hostCookies, true).getBytes(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);

			System.out.println("cookie update :"+path);
		} catch (URISyntaxException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}